package framework.view.components.scrollbar
{
import flash.display.DisplayObject;
import flash.display.DisplayObjectContainer;
import flash.display.Sprite;
import flash.events.Event;
import flash.events.MouseEvent;
import flash.geom.Rectangle;

import framework.view.events.ScrollBarEvent;

/**
 *
 * @author v-jliang
 *
 */
public class ScrollBarThumb extends Sprite
{
    //==========================================================================
    //  Class constants
    //==========================================================================
    protected static const TOP_ARROW:String = "topArrow";
    protected static const BOTTOM_ARROW:String = "bottomArrow";
    protected static const BG:String = "bg";
    protected static const SYMBOL:String = "symbol";

    //==========================================================================
    //  Constructor
    //==========================================================================
    public function ScrollBarThumb()
    {
        super();
        init();
    }
    //==========================================================================
    //  Variables
    //==========================================================================
    protected var defaultHeight:Number;

    protected var thumbAsset:DisplayObjectContainer;

    protected var topArrow:DisplayObject;
    protected var bottomArrow:DisplayObject;
    protected var bg:DisplayObject;
    protected var symbol:DisplayObject;
    //==========================================================================
    //  Properties
    //==========================================================================
    protected var _scrollArea:Rectangle;

    public function set scrollArea(value:Rectangle):void
    {
        _scrollArea = value;
        this.y = _scrollArea.y;
    }

    public function get scrollArea():Rectangle
    {
        return _scrollArea;
    }

    protected var _value:Number = 0;

    public function set value(v:Number):void
    {
        if (v > 1)
        {
            v = 1;
        }
        else if (v < 0)
        {
            v = 0;
        }
        this._value = v;
        this.y = this._scrollArea.y + this._scrollArea.height * this._value;
    }

    public function get value():Number
    {
        return this._value;
    }

    public function set skin(value:DisplayObjectContainer):void
    {
        if (thumbAsset && this.contains(thumbAsset))
        {
            this.removeChild(thumbAsset);
            thumbAsset = null;
        }
        thumbAsset = value;
        this.addChild(thumbAsset);
        setSkin();
    }
	
	public function get skin():DisplayObjectContainer
	{
		return thumbAsset;
	}
    //==========================================================================
    //  Overridden methods: ScollBarThumbAsset
    //==========================================================================
    override public function set height(value:Number):void
    {
        if (defaultHeight > value)
        {
            value = defaultHeight;
        }
        if (value < (this.topArrow.height + this.bottomArrow.height))
        {
            value = this.topArrow.height + this.bottomArrow.height;
        }
        this.bg.height = value - this.topArrow.height - this.bottomArrow.height;
        this.bg.y = this.topArrow.y + this.topArrow.height;
        this.bottomArrow.y = this.bg.y + this.bg.height;

        this.symbol.y = this.bg.y + (this.bg.height - this.symbol.height) / 2;
    }
    //==========================================================================
    //  Public methods
    //==========================================================================
    public function dispose():void
    {
        this.removeEventListener(Event.ADDED_TO_STAGE, addToStageHandler);
        this.removeEventListener(MouseEvent.MOUSE_DOWN, mouseDownHandler);
        clearEventListener();
        _scrollArea = null;
    }
    //==========================================================================
    //  Protected methods
    //==========================================================================
    protected function init():void
    {
		var sp:Sprite = new Sprite();
		
		var spTop:Sprite = new Sprite();
		spTop.graphics.beginFill(0x000000, 1);
		spTop.graphics.drawRect(0, 0, 5, 10);
		spTop.graphics.endFill();
		spTop.name = TOP_ARROW;
		
		var spBg:Sprite = new Sprite();
		spBg.graphics.beginFill(0x000000, 1);
		spBg.graphics.drawRect(0, 0, 5, 30);
		spBg.graphics.endFill();
		spBg.y = spTop.height;
		spBg.name = BG;
		
		var spBottom:Sprite = new Sprite();
		spBottom.graphics.beginFill(0x000000, 1);
		spBottom.graphics.drawRect(0, 0, 5, 10);
		spBottom.graphics.endFill();
		spBottom.y = spBg.y + spBg.height;
		spBottom.name = BOTTOM_ARROW;
		
		var spSymbol:Sprite = new Sprite();
		spSymbol.x = spBg.width / 2;
		spSymbol.y = spBg.y + spBg.height / 2;
		spSymbol.name = SYMBOL;
		
		sp.addChild(spTop);
		sp.addChild(spBg);
		sp.addChild(spBottom);
		sp.addChild(spSymbol);
		
        thumbAsset = sp;
        this.addChild(thumbAsset);
        setSkin();

        this.buttonMode = true;
        this.useHandCursor = true;
        this.addEventListener(Event.ADDED_TO_STAGE, addToStageHandler);
    }

    protected function setSkin():void
    {
        this.topArrow = thumbAsset.getChildByName(TOP_ARROW);
        this.bottomArrow = thumbAsset.getChildByName(BOTTOM_ARROW);
        this.bg = thumbAsset.getChildByName(BG);
        this.symbol = thumbAsset.getChildByName(SYMBOL);

        defaultHeight = this.height;
        
        this.width = Math.ceil(this.width);
		height = defaultHeight;
    }

    protected function setupEventListener():void
    {
        if (stage)
        {
            this.stage.addEventListener(MouseEvent.MOUSE_MOVE,
                                        mouseMoveHandler);
            this.stage.addEventListener(MouseEvent.MOUSE_UP, mouseUpHandler);
        }
    }

    protected function clearEventListener():void
    {
        if (stage)
        {
            this.stage.removeEventListener(MouseEvent.MOUSE_MOVE,
                                           mouseMoveHandler);
            this.stage.removeEventListener(MouseEvent.MOUSE_UP, mouseUpHandler);
        }
    }

    //==========================================================================
    //  Event handlers
    //==========================================================================
    protected function addToStageHandler(event:Event):void
    {
        this.removeEventListener(Event.ADDED_TO_STAGE, addToStageHandler);
        this.addEventListener(MouseEvent.MOUSE_DOWN, mouseDownHandler);
    }

    protected function mouseDownHandler(event:MouseEvent):void
    {
        this.startDrag(false, new Rectangle(this.x, _scrollArea.y,
                                            0, _scrollArea.height));
        setupEventListener();
    }

    protected function mouseMoveHandler(event:MouseEvent):void
    {
        this.y = Math.ceil(this.y);
        var val:Number = this.y - this._scrollArea.y;
        if (val > this._scrollArea.height)
        {
            this.y = this._scrollArea.height + this._scrollArea.y;
        }
        this.value = val / this._scrollArea.height;
        this.dispatchEvent(new ScrollBarEvent(ScrollBarEvent.CHANGE, true));
    }

    protected function mouseUpHandler(event:MouseEvent):void
    {
        this.stopDrag();
        clearEventListener();
        this.dispatchEvent(new ScrollBarEvent(ScrollBarEvent.CHANGE, true));
    }
}
}

